from odoo import fields, models, api
from odoo.exceptions import UserError
import math
from ...functions.book_pickup_fc import BookPickupFC as BookPickup
from odoo.addons.rp_customer_management.models.inherit.res_partner_inherit_for_customer import ADDRESS_TYPE

TRACKING_STATE = [('created', '已创建'), ('in_transit', '运输中'), ('delivery', '派送中'), ('delivered', '已送达'), ('exception', '异常'), ('failed_attempt', '错误尝试'), ('cancel', '作废')]


class RPShipment(models.Model):
    _name = 'rp.shipment'
    _description = '运输单'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _rec_name = 'code'
    _order = 'create_date DESC'

    def _default_get_kg(self):
        kg = self.env['uom.uom'].search([('name', '=', 'kg')])
        return kg.id if kg else False

    def _default_get_cm3(self):
        cm = self.env['uom.uom'].search([('name', '=', 'cm³')])
        return cm.id if cm else False

    code = fields.Char(string='运输单号', default='RP_SP/20230101/*****', readonly=True, copy=False, index=True, tracking=True)
    rp_ship_order_id = fields.Many2one(string='订单', comodel_name='rp.ship.order', tracking=True)

    weight_uom_id = fields.Many2one(string='重量单位', comodel_name='uom.uom', default=_default_get_kg)
    volume_uom_id = fields.Many2one(string='体积单位', comodel_name='uom.uom', default=_default_get_cm3)
    currency_id = fields.Many2one(string='货币单位', comodel_name='res.currency', default=lambda self: self.env.company.currency_id)

    state = fields.Selection(string='状态', selection=TRACKING_STATE, default='created', tracking=True)

    customer_id = fields.Many2one(string='客户', comodel_name='rp.customer')

    send_country_id = fields.Many2one(string='发件国家', comodel_name='res.country', tracking=True)
    send_postal_code_id = fields.Many2one(string='发件邮编', comodel_name='rp.postal.code', tracking=True)
    send_state_id = fields.Many2one(string='发件省', comodel_name='res.country.state', compute='_depends_send_postal_code_id', store=True)
    send_city_id = fields.Many2one(string='发件市', comodel_name='res.city', compute='_depends_send_postal_code_id', store=True)
    send_street = fields.Char(string='发件街道', tracking=True)
    send_first_name = fields.Char(string='发件人名', tracking=True)
    send_last_name = fields.Char(string='发件人姓', tracking=True)
    send_phone = fields.Char(string='发件电话', tracking=True)
    send_address_type = fields.Selection(string='发件地址类型', selection=ADDRESS_TYPE, default=ADDRESS_TYPE[0][0], tracking=True)
    send_company_name = fields.Char(string='发件公司名称', tracking=True)
    send_email = fields.Char(string='发件人邮箱')

    receive_country_id = fields.Many2one(string='收件国家', comodel_name='res.country', tracking=True)
    receive_postal_code_id = fields.Many2one(string='收件邮编', comodel_name='rp.postal.code', tracking=True)
    receive_state_id = fields.Many2one(string='收件省', comodel_name='res.country.state', compute='_depends_receive_postal_code_id', store=True)
    receive_city_id = fields.Many2one(string='收件市', comodel_name='res.city', compute='_depends_receive_postal_code_id', store=True)
    receive_street = fields.Char(string='收件街道', tracking=True)
    receive_first_name = fields.Char(string='收件人名', tracking=True)
    receive_last_name = fields.Char(string='收件人姓', tracking=True)
    receive_phone = fields.Char(string='收件电话', tracking=True)
    receive_address_type = fields.Selection(string='发件地址类型', selection=ADDRESS_TYPE, default=ADDRESS_TYPE[0][0], tracking=True)
    receive_company_name = fields.Char(string='收件公司名称', tracking=True)
    receive_email = fields.Char(string='收件人邮箱')

    shipper_id = fields.Many2one(string='托运商', comodel_name='rp.shipper', tracking=True)
    shipper_mail_route_id = fields.Many2one(string='托运商邮路', comodel_name='rp.shipper.mail.route', tracking=True)
    package_type_id = fields.Many2one(string='包裹类型', comodel_name='rp.package.type', tracking=True)
    aging_id = fields.Many2one(string='时效', comodel_name='rp.aging')

    pickup_flag = fields.Boolean(string='上门取件', default=False, tracking=True)
    dropoff_flag = fields.Boolean(string='网点收件', default=False, tracking=True)
    delivery_flag = fields.Boolean(string='送货上门', default=False, tracking=True)
    collect_flag = fields.Boolean(string='网点取件', default=False, tracking=True)
    head_postal_outlet_id = fields.Many2one(string='头程网点', comodel_name='rp.courier.postal.outlet')
    tail_postal_outlet_id = fields.Many2one(string='尾程网点', comodel_name='rp.courier.postal.outlet')
    book_pickup_id = fields.Many2one(string='预约上门取件', comodel_name='rp.book.pickup')

    rp_parcel_ids = fields.Many2many(string='包裹明细', comodel_name='rp.parcel',
                                     relation='rp_shipment_and_parcel_rel', column1='shipment_id', column2='parcel_id')
    parcel_total_weight = fields.Float(string='包裹总重量', digits=(8, 3), default=0)
    parcel_total_volume = fields.Float(string='包裹总体积', digits=(8, 3), default=0)
    parcel_total_values = fields.Float(string='包裹总价值', digits=(8, 3), default=0)
    parcel_actual_weight = fields.Float(string='包裹实际重量', digits=(8, 3), default=0)
    parcel_rounded_weight = fields.Float(string='包裹取整重量', digits=(8, 3), default=0)

    rp_shipment_value_added_line_ids = fields.One2many(string='增值服务明细', comodel_name='rp.shipment.value.added.line', inverse_name='rp_shipment_id')

    mail_route_price = fields.Float(string='邮路价格', digits=(8, 3), default=0)
    fulfillment_price = fields.Float(string='头尾程价格', digits=(8, 3), default=0)
    value_added_price = fields.Float(string='增值服务价格', digits=(8, 3), default=0)
    total_price = fields.Float(string='总价格', digits=(8, 3), default=0)
    label_picture_ids = fields.Many2many(string='面单图片', comodel_name='ir.attachment', column1='rp_shipment_id', column2='ir_attachment_id', relation='rp_shipment_ir_attachment_rel', copy=False)

    # label_url = fields.Char(string='面单地址')
    # label_pdf_ids = fields.Many2many(string='面单', comodel_name='ir.attachment',
    #                                  relation="rp_shipment_attachment_ref", column1='shipment_id', column2='attachment_id')
    # tracking_external_link = fields.Char(string='追踪外链')

    remarks = fields.Text(string='备注', tracking=True)

    active_flag = fields.Boolean(string='有效', default=True, tracking=True)

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            vals['code'] = self.env['ir.sequence'].sudo().next_by_code('rp.shipment') or '/'
        return super(RPShipment, self).create(vals_list)

    @api.depends('send_postal_code_id')
    def _depends_send_postal_code_id(self):
        """ 填入发件邮编自动填充发件省、市 """
        for s in self:
            if s.send_postal_code_id:
                s.write({'send_state_id': s.send_postal_code_id.state_id.id,
                         'send_city_id': s.send_postal_code_id.city_id.id})

    @api.depends('receive_postal_code_id')
    def _depends_receive_postal_code_id(self):
        """ 填入收件邮编自动填充收件省、市 """
        for s in self:
            if s.receive_postal_code_id:
                s.write({'receive_state_id': s.receive_postal_code_id.state_id.id,
                         'receive_city_id': s.receive_postal_code_id.city_id.id})

    def cancel_shipment(self):
        """ 作废运单，只有未发货时 """
        if self.state == 'created':
            # 1、同步作废预约上门单，如果有的话
            self.book_pickup_id.cancel_book()
            # 2、作废运单
            self.write({'state': 'cancel', 'remarks': '已手动作废', 'active_flag': False})
            # 3、订单取消关联
            old_remarks = self.rp_ship_order_id.remarks if self.rp_ship_order_id.remarks else ''
            new_remarks = '运单号:{} 已手动作废;'.format(self.code)
            self.rp_ship_order_id.write({'shipment_flag': False, 'remarks': old_remarks + new_remarks})
        else:
            raise UserError("不在未发货状态")

    def create_book_pickup(self):
        """ 创建上门取件 """
        if self.pickup_flag:
            book_pickup = BookPickup(self.env).shipment_create_book_pickup(self)
            self.write({'book_pickup_id': book_pickup.id})
            self.action_open_book_pickup()
            pass
        else:
            raise UserError('该运单非上门取件，无法预约')

    def action_open_book_pickup(self):
        """ 打开相关的上门视图 """
        self.ensure_one()
        action = self.env.ref('rp_shipment_management.action_rp_book_pickup')
        result = action.read()[0]
        book_pickup_rcds = self.env['rp.book.pickup'].search([('shipment_id', '=', self.id)])
        view_form = self.env.ref('rp_shipment_management.rp_book_pickup_form', False)
        if len(book_pickup_rcds) == 1:
            result['views'] = [(view_form and view_form.id or False, 'form')]
            result['res_id'] = book_pickup_rcds.id
        else:
            result['view_mode'] = 'list,form'
            result['context'] = {'search_default_is_use': 1, 'search_default_not_use': 1}
            result['domain'] = [('id', 'in', book_pickup_rcds.ids)]
        return result


class RPShipmentValueAddedLine(models.Model):
    _name = 'rp.shipment.value.added.line'
    _description = '运单增值服务明细'

    rp_shipment_id = fields.Many2one(string='关联运单', comodel_name='rp.shipment', ondelete='cascade')
    currency_id = fields.Many2one(string='货币单位', comodel_name='res.currency', default=lambda self: self.env.company.currency_id)

    value_added_id = fields.Many2one(string='增值服务', comodel_name='rp.value.added.service')
    value_added_type = fields.Selection(string='类型', related='value_added_id.type', store=True)
    value_added_category = fields.Selection(string='增值服务等级', related='value_added_id.category', store=True)

    price = fields.Float(string='价格', digits=(5, 3), default=0)
